﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aoxuelf.MDSTool.Model;
using System.Xml;

namespace Aoxuelf.MDSTool.SQL
{
    public class ConvertToBLLMethodWriter : MethodWriter
    {
        public ConvertToBLLMethodWriter(ConvertToBLLMethodInfo methodWriteInfo)
            : base(methodWriteInfo)
        {
        }

        private bool IsSave
        {
            get { return ((ConvertToBLLMethodInfo)this.methodWriteInfo).IsSave; }
        }

        public string DocComment
        {
            get { return ((ConvertToBLLMethodInfo)this.methodWriteInfo).DocComment; }
        }

        public string DALClass
        {
            get { return ((ConvertToBLLMethodInfo)this.methodWriteInfo).DALClass; }
        }

        public override string Write()
        {
            builder = new StringBuilder();
            WriteDocComment();
            WriteMethod();

            return builder.ToString();
        }

        private void WriteDocComment()
        {
            XmlDocument doc = new XmlDocument();
            doc.PreserveWhitespace = true;
            doc.LoadXml(DocComment);
            var nodeRets = doc.DocumentElement.SelectNodes("returns");
            if (nodeRets.Count == 0)
            {
                XmlElement ele = doc.CreateElement("returns");
                doc.DocumentElement.AppendChild(ele);
            }

            var nodeTran = doc.DocumentElement.SelectSingleNode("param[@type='DbTransaction']");
            if (nodeTran != null)
            {
                doc.DocumentElement.RemoveChild(nodeTran);
            }

            var node = doc.DocumentElement.SelectSingleNode("returns");
            AddContent(node, ReturnContent.Exe_Flag);
            AddContent(node, ReturnContent.Exe_UserMsg);

            string[] commentList = doc.DocumentElement.InnerXml.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (string comment in commentList)
            {
                builder.AppendLine("/// " + comment);
            }
        }

        private void AddContent(XmlNode node, ReturnContent content)
        {
            var nodes = node.SelectNodes(string.Format("content[@name='{0}']", content.Name));
            if (nodes.Count == 0)
            {
                var contentEle = node.OwnerDocument.CreateElement("content");
                contentEle.InnerText = content.Text;

                var typeAttr = node.OwnerDocument.CreateAttribute("type");
                typeAttr.Value = content.Type;
                contentEle.Attributes.Append(typeAttr);

                var nameAttr = node.OwnerDocument.CreateAttribute("name");
                nameAttr.Value = content.Name;
                contentEle.Attributes.Append(nameAttr);

                node.AppendChild(contentEle);
                node.AppendChild(node.OwnerDocument.CreateSignificantWhitespace("\r"));
            }
        }

        protected override void WriteMethodSig()
        {
            string format = "public IDictionary<string, object> {0}(IDictionary<string, object> dicParam)";
            if (!IsSave)
            {
                format = "public IDictionary<string, object> {0}(IDictionary<string, string> dicParam)";
            }

            builder.AppendLine(string.Format(format, methodWriteInfo.MethodName));
        }

        protected override void WriteMethodBody()
        {
            if (IsSave)
            {
                WriteSaveMethodBody();
            }
            else
            {
                WriteQueryMethodBody();
            }
        }

        private void WriteSaveMethodBody()
        {
            builder.AppendLine("IDictionary<string, object> dicRet = new Dictionary<string, object>();");
            builder.AppendLine("DbTransaction tran = Gateway.Default.BeginTransaction();");
            builder.AppendLine("");
            builder.AppendLine("try");
            builder.AppendLine("{");
            builder.AppendLine(string.Format("    {0} dal = new {0}();", DALClass));
            builder.AppendLine(string.Format("    dal.{0}(tran, dicParam);", methodWriteInfo.MethodName));
            builder.AppendLine("    tran.Commit();");
            builder.AppendLine("    dicRet = ExecutionResult.Success(\"保存成功！\");");
            builder.AppendLine("}");
            builder.AppendLine("catch (Exception ex)");
            builder.AppendLine("{");
            builder.AppendLine("    if (tran != null)");
            builder.AppendLine("    {");
            builder.AppendLine("        tran.Rollback();");
            builder.AppendLine("    }");
            builder.AppendLine("    dicRet = ExceptionHelper.ExceptioinManage(ex, dicRet);");
            builder.AppendLine("    return dicRet;");
            builder.AppendLine("}");
            builder.AppendLine("finally");
            builder.AppendLine("{");
            builder.AppendLine("    if (tran != null)");
            builder.AppendLine("    {");
            builder.AppendLine("        tran.Dispose();");
            builder.AppendLine("    }");
            builder.AppendLine("}");
            builder.AppendLine("");
            builder.AppendLine("return dicRet;");
        }

        private void WriteQueryMethodBody()
        {
            builder.AppendLine("IDictionary<string, object> dicRet = new Dictionary<string, object>();");
            builder.AppendLine("");
            builder.AppendLine("try");
            builder.AppendLine("{");
            builder.AppendLine(string.Format("    {0} dal = new {0}();", DALClass));
            bool isPage = this.DocComment.Contains("#TOTAL_PAGE#");
            if (isPage)
            {
                builder.AppendLine(string.Format("    dicRet = dal.{0}(dicParam);", methodWriteInfo.MethodName));
            }
            else
            {
                builder.AppendLine(string.Format("    DataTable dt = dal.{0}(dicParam);", methodWriteInfo.MethodName));
                builder.AppendLine("");
                builder.AppendLine("    dicRet[\"DT\"] = dt;");
                builder.AppendLine("    dicRet = ExecutionResult.QuerySuccess();");
            }
            builder.AppendLine("}");
            builder.AppendLine("catch (Exception ex)");
            builder.AppendLine("{");
            builder.AppendLine("    dicRet = ExceptionHelper.ExceptioinManage(ex, dicRet);");
            builder.AppendLine("    return dicRet;");
            builder.AppendLine("}");
            builder.AppendLine("");
            builder.AppendLine("return dicRet;");
        }
    }
}
